import { loadEnv } from "vite";
import type { ConfigEnv, UserConfigExport, ProxyOptions } from "vite";
import { fileURLToPath } from "url";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { viteMockServe } from "vite-plugin-mock";
import { createHtmlPlugin } from "vite-plugin-html";
import AutoImport from "unplugin-auto-import/vite";
import Icons from "unplugin-icons/vite";
import Components from "unplugin-vue-components/vite";
import IconsResolver from "unplugin-icons/resolver";
import ElementPlus from "unplugin-element-plus/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import tsChecker from "vite-plugin-checker";

import configItem from "./config/index";
import path from "path";

export default ({ mode }: ConfigEnv): UserConfigExport => {
  const {
    VITE_APP_PORT,
    VITE_APP_PROXY,
    VITE_MOCK,
    VITE_APP_BASE_URL,
    VITE_APP_NAME,
    VITE_APP_OUTPUT_DIR,
    VITE_NODE_ENV,
  } = loadEnv(mode, process.cwd());

  const _Config = configItem[VITE_APP_NAME || "DEFAULT"];

  const createProxy = (proxyList: any) => {
    const ret = {} as Record<string, ProxyOptions>;
    for (const [prefix, target] of proxyList) {
      ret[prefix] = {
        target,
        changeOrigin: true,
        rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ""),
      };
    }
    return ret;
  };

  // 获取当前工作目录
  const root = process.cwd();
  // 获取环境变量
  const env = loadEnv(mode, root);

  const plugins = [
    // Vue模板文件编译插件
    vue(),
    // jsx文件编译插件
    vueJsx(),
    // 开启ElementPlus自动引入CSS
    ElementPlus({}),
    // 自动引入组件及ICON
    AutoImport({
      resolvers: [IconsResolver(), ElementPlusResolver()],
      dts: fileURLToPath(new URL("./types/auto-imports.d.ts", import.meta.url)),
    }),
    // 自动注册组件
    Components({
      resolvers: [IconsResolver(), ElementPlusResolver()],
      dts: fileURLToPath(new URL("./types/components.d.ts", import.meta.url)),
    }),
    // 自动安装图标
    Icons({
      autoInstall: true,
    }),
    createHtmlPlugin({
      minify: true,
      template: "public/index.html",
      inject: {
        data: {
          title: _Config.BASE_TITLE,
          icon: _Config.BASE_ICON,
        },
      },
    }),
  ];

  // 先本地开发检查
  if (VITE_NODE_ENV === "development") {
    plugins.push(
      tsChecker({
        vueTsc: true,
        overlay: false,
      }),
    );
  }

  if (VITE_MOCK === "true") {
    plugins.push(
      viteMockServe({
        mockPath: "mock",
        //在 vite-plugin-mock 的新版本中，localEnabled 属性已经被 enable 所取代。
        enable: mode === "development", // 仅在开发环境启用,
      }),
    );
  }

  return {
    // 项目根目录
    root,
    // 项目部署的基础路径
    base: _Config.BASE_URL[mode] || VITE_APP_BASE_URL,
    publicDir: fileURLToPath(new URL("./public", import.meta.url)), // 无需处理的静态资源位置
    assetsInclude: fileURLToPath(new URL("./src/assets", import.meta.url)), // 需要处理的静态资源位置
    plugins,
    // 运行后本地预览的服务器
    server: {
      // 是否开启https
      // https: {},
      host: true,
      // 开发环境预览服务器端口
      port: Number(VITE_APP_PORT),
      // 启动后是否自动打开浏览器
      open: true,
      // 是否开启CORS跨域
      cors: true,
      // 代理服务器
      // proxy: createProxy(JSON.parse(VITE_APP_PROXY)),
      proxy: _Config.BASE_PROXY,
    },
    // 打包配置
    build: {
      outDir: VITE_APP_OUTPUT_DIR,
      // 关闭 sorcemap 报错不会映射到源码
      sourcemap: false,
      // 打包大小超出 400kb 提示警告
      chunkSizeWarningLimit: 1000,
      rollupOptions: {
        // 打包入口文件 根目录下的 index.html
        // 也就是项目从哪个文件开始打包
        input: {
          index: fileURLToPath(new URL("./index.html", import.meta.url)),
        },
        // 静态资源分类打包
        output: {
          format: "esm",
          chunkFileNames: `static/js/[name].${_Config.BASE_HASH}.js`,
          entryFileNames: `static/js/[name].${_Config.BASE_HASH}.js`,
          assetFileNames: `static/[ext]/[name].${_Config.BASE_HASH}.[ext]`,
        },
      },
    },
    // 配置别名
    resolve: {
      alias: {
        "@": path.resolve(__dirname, "src"),
      },
      extensions: [".ts", ".tsx", ".js", ".m.js"],
    },
  };
};
